<?php
header('Content-type: text/html; charset=UTF-8') ;
/*
---------LICENSE----------
You may modify this code as you see fit, for your own personal
use on your or your guild's website, providing you leave this license
intact. You may not make this file or any derivative of this file, or 
any archive containing this file or a derivative of this file available 
for download on any website without the express written consent of an
authorized representative of WoWSim.
*/

//Age, beyond which cached armory data is considered "out of date"
$staleCachedItemTime = 60*60*48; //48 hours
//Amount of time to wait between armory requests, in miliseconds. NOTE: setting this lower than 1500 may result in a 12 hour armory IP ban
$waitBetweenArmoryRequests = 1500.0;

$connected = false;

/////////////////////////
// Cache database info //
/////////////////////////
//server/////////
$cacheDbServer = "localhost";
//username///////
$cacheDbServerU = "pulsarwe_armCach";
//password///////
$cacheDbServerP = "lollerskates123";
//database name//
$cacheDbName = "pulsarwe_armCache";
//table name/////
$cacheDbTableName = "ArmCache";
//////////////////////////
//////////////////////////
//////////////////////////
$cacheConnection;

$using="utf8";

//Keep track of the last time to query, in order to make sure we don't request pages so quickly that we earn ourselves a 12 hour IP ban
$lastArmoryQueryTimeS = 0;
$lastArmoryQueryTimeU = 0;

//Get the remaining time we have to wait before requesting an armory page.
function getRemainingArmoryWaitTime()
{
  global $lastArmoryQueryTimeS, $lastArmoryQueryTimeU,$waitBetweenArmoryRequests;
  list($usec, $sec) = explode(" ", microtime());
  $elapsedUs = 1000*($sec - $lastArmoryQueryTimeS) + 1000*($usec - $lastArmoryQueryTimeU);
  if($elapsedUs >= $waitBetweenArmoryRequests)
    return 0;
  else 
    return (int)($waitBetweenArmoryRequests - $elapsedUs);
}

//Connect to the armory cache DB
function WSArmory_cacheConnect() {
  global $cacheDbServer,$cacheDbServerU,$cacheDbServerP,$cacheDbName,$cacheDbTableName;
  global $connected, $cacheConnection;
  if($connected == false) 
    {
      $cacheConnection = mysql_connect($cacheDbServer,$cacheDbServerU,$cacheDbServerP);
      mysql_select_db($cacheDbName);
      $connected = true;
    }
}

//Diagnostics. Only run if diagnostics=true is in the URL of this page
if($_GET['diagnostics']) {
  echo "<em>WoWSim Armory Core Diagnostics</em><hr><em>-----WSArmoryCore.php-----</em><br>";
  $passStr = "<strong><font color=\"#55aa55\">[PASS]</font></strong>";
  $failStr = "<strong><font color=\"#aa5555\">[FAIL]</font></strong>";
  
  echo"Database Test...";
  WSArmory_cacheConnect();
  if($cacheConnection)
    echo $passStr."<br>";
  else
    die($failStr."<br>");

  echo"Guild Data Test...";
  if(WSArmory_getGuildXML("http://www.wowarmory.com","Bleach","Azjol-Nerub"))
    echo $passStr."<br>";
  else
    echo $failStr."<br>";

  echo "Character Sheet Test...";
  if(WSArmory_getCharacterSheetXML("http://www.wowarmory.com","Strydaris","Azjol-Nerub"))
    echo $passStr."<br>";
  else
    echo $failStr."<br>";

  echo "Character Arena Teams Test...";
  if(WSArmory_getCharacterArenaTeamsXML("http://www.wowarmory.com","Strydaris","Azjol-Nerub"))
    echo $passStr."<br>";
  else
    echo $failStr."<br>";

  echo "Annoying Character Set Test...";
  if(WSArmory_getCharacterSheetXML("http://www.wowarmory.com","The&#223ack","Azjol-Nerub"))
    echo $passStr."<br>";
  else
    echo $failStr."<br>";

  echo "Character Talents Test...";
  if(WSArmory_getCharacterTalentsXML("http://www.wowarmory.com","Strydaris","Azjol-Nerub"))
    echo $passStr."<br>";
  else
    echo $failStr."<br>";

  echo "Arena Team Info Test...";
  if(WSArmory_getArenaTeamXML("http://www.wowarmory.com","Dash and Crash","Azjol-Nerub",2))
    echo $passStr."<br>";
  else
    echo $failStr."<br>";

  echo "Item Info Test...";
  if(WSArmory_getItemInfoXML("http://www.wowarmory.com",40722))
    echo $passStr."<br>";
  else
    echo $failStr."<br>";

  
  echo "Character Achievements Test...";
  if(WSArmory_getAchievementsXML("http://www.wowarmory.com","Strydaris","Azjol-Nerub"))
    echo $passStr."<br>";
  else
    echo $failStr."<br>";
  
  echo "Character Achievement Category Test...";
  if(WSArmory_getAchievementCategoryXML("http://www.wowarmory.com","Strydaris","Azjol-Nerub",168))
    echo $passStr."<br>";
  else
    echo $failStr."<br>";

}

//Get a character sheet, for a provided armory domain name, a character name and a realm's name.
function WSArmory_getCharacterSheetXML($baseURL, $name, $realm) {
  $url = $baseURL."/character-sheet.xml?r=".$realm."&n=".$name;
  return WSArmory_getArmoryXML($url);
}
//Get a character's arena team info, for a specified armory domain name, a character name, and a realm's name.
function WSArmory_getCharacterArenaTeamsXML($baseURL, $name, $realm) {
  $url = $baseURL."/character-arenateams.xml?r=".$realm."&n=".$name;
  return WSArmory_getArmoryXML($url);
}
//Get character talent info, for a specified armory domain name, a character name and its realm's name
function WSArmory_getCharacterTalentsXML($baseURL, $name, $realm) {
  $url = $baseURL."/character-talents.xml?r=".$realm."&n=".$name;
  return WSArmory_getArmoryXML($url);
}
//Get item info for a specified armory domain name, and an item ID (integer)
function WSArmory_getItemInfoXML($baseURL,$itemId) {
  $url = $baseURL."/item-info.xml?i=".$itemId;
  return WSArmory_getArmoryXML($url);
}
//Get guild info for a specified armory domain name, the guild's name, and it's realm's name
function WSArmory_getGuildXML($baseURL, $name, $realm) {
  $url = $baseURL."/guild-info.xml?r=".$realm."&n=".$name; 
  return WSArmory_getArmoryXML($url);
}
//Get information about an arena team for a specified armory doman name, given the team's name, realm and size (2, 3 or 5)
function WSArmory_getArenaTeamXML($baseURL, $name, $realm, $size) {
  $url= $baseURL."/team-info.xml?r=".$realm."&ts=".$size."&t=".$name."&select=".$name;
  return WSArmory_getArmoryXML($url);
}

//Get information about a character's achievements, given the character's name and realm
function WSArmory_getAchievementsXML($baseURL,$name,$realm) {
  $url=$baseURL."/character-achievements.xml?r=".$realm."&n=".$name;
  return WSArmory_getArmoryXML($url);
}

//Get information about an achievement category, given the character's name and realm
function WSArmory_getAchievementCategoryXML($baseURL,$name,$realm,$categoryId) {
  $url=$baseURL."/character-achievements.xml?r=".$realm."&n=".$name."&c=".$categoryId;
  return WSArmory_getArmoryXML($url);
}

//trim the armory domain from an armory URL. For example:
//  http://www.wowarmory.com/character-sheet.xml?r=Azjol-Nerub&n=Strydaris
//  becomes
//  character-sheet.xml?r=Azjol-Nerub&n=Strydaris
function WSArmory_trimArmoryURL($raw) {
  $result = strchr($raw,"guild");
  if($result == false)
    $result = strchr($raw,"character");
  if($result == false)
    $result = strchr($raw,"item");
  if($result == false)
    $result = strchr($raw,"team");  
  return $result;
}

//Try to get cached armory XML for a given URL
$cacheConnection;
function WSArmory_getArmoryXMLFromCache($url) {
  WSArmory_cacheConnect();
  global $cacheDbTableName,$using;
  $selectString = "SELECT * FROM ".$cacheDbTableName." WHERE `url` LIKE CONVERT( _utf8 '".WSArmory_trimArmoryURL($url)."' USING $using)";
  $selectResult = mysql_query($selectString);
  if($selectResult) {
    $row = mysql_fetch_array($selectResult);
    if($row) {
      return $row[1];
    } else
      return false;
  } else 
    return false;    
}

//Put armory XML into the cache. This takes care of replacing stale data, if necessary.
function WSArmory_putArmoryXMLInCache($url, $data) {
  WSArmory_cacheConnect();
  global $cacheDbTableName,$cacheDbName,$staleCachedItemTime,$using;
  
  $selectString = "SELECT * FROM `".$cacheDbTableName."` WHERE `url` LIKE CONVERT( _utf8 '".WSArmory_trimArmoryURL($url)."' USING $using)";
  $selectResult = mysql_query($selectString);

  if($selectResult) 
    {
      $row = mysql_fetch_row($selectResult);

      $age = time() - $row[2];
      if($age > $staleCachedItemTime) 
	{
	  $removeString = "DELETE FROM `".$cacheDbName."`.`".$cacheDbTableName."` WHERE CONVERT(`".$cacheDbTableName."`.`url` USING utf8) = \"".WSArmory_trimArmoryURL($url)."\"";
	  
	  $removeResult = mysql_query($removeString);
	  if(!$removeResult) {
	    WSArmory_ErrorXML("MySQL Error ".mysql_error(),$data);
	  }
	  $insertString = "INSERT INTO `".$cacheDbName."`.`".$cacheDbTableName."` (`url` ,`xmlString`,`updateTime`) VALUES (\"".WSArmory_trimArmoryURL($url)."\", \"". htmlentities($data)."\",".time().");";
	  
	  $insertResult = mysql_query($insertString);
	  
	  if(!$insertResult) {
	    WSArmory_ErrorXML("MySQL Error: ".mysql_error(),$data);    
	  }
	}
    } else {
      echo "SQL ERR: ".mysql_error()."<br>";
      $insertString = "INSERT INTO `".$cacheDbName."`.`".$cacheDbTableName."` (`url` ,`xmlString`,`updateTime`) VALUES (\"".WSArmory_trimArmoryURL($url)."\", \"". htmlentities($data)."\",".time().");";
      
      $insertResult = mysql_query($insertString);
      
      if(!$insertResult) {
	WSArmory_ErrorXML("MySQL Error: ".mysql_error(),$data);    
      }
    }  
}

//Get XML from the World of Warcraft armory
function WSArmory_getArmoryXML($url) {
  $cached = WSArmory_getArmoryXMLFromCache($url);
  if($cached) {    
     $f = html_entity_decode($cached);
  } else {
    $ch = curl_init();
    $useragent="Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.1) Gecko/20061204 Firefox/2.0.0.1";

    echo "URL: " . $url;
    curl_setopt ($ch, CURLOPT_URL, $url);
    curl_setopt ($ch, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt ($ch, CURLOPT_USERAGENT, $useragent);
    
    $remainingWait = getRemainingArmoryWaitTime();
    
    if($remainingWait > 0) {
      usleep($remainingWait*1000);
    }
    
    $f = curl_exec($ch);
    
    global $lastArmoryQueryTimeS, $lastArmoryQueryTimeU;
    list($usec,$sec) = explode(" ",microtime());
    $lastArmoryQueryTimeS = $sec;
    $lastArmoryQueryTimeU = $usec;
    
    curl_close($ch);
  }

  $xml = simplexml_load_string($f);
  if($xml && ($xml->guildInfo[0] || $xml->characterInfo[0] || $xml->teamInfo[0] || $xml->itemInfo[0]) || $xml->category[0]) {
    WSArmory_putArmoryXMLInCache($url,$f);
    return $xml;
  }
  else {
    WSArmory_errorXML("Invalid data (or no data) at <a href=\"".$url."\">".$url."</a>",$f);
  }
}

//Generate an error message, given the message and the relevant XML
function WSArmory_errorXML($message, $data) {
  $msg = "<center><font color=red>ERROR: " . $message."</font>";
  if($data)
    $msg = $msg."<div style=\"width:70%; background:grey; color:white;\">".htmlentities($data)."</div>";
  $msg = $msg."</center>";
  die($msg);
}
  
?>